#pragma once
#include <iostream>
#include <string>
#include <functional>
#include <utility>
#include <cstring>
#include <cstdio>
#include <pthread.h>
#include <tuple>

namespace ThreadModule
{
    class Thread
    {
    private:
        static void *start_routine(void *args)
        {
            auto taskPtr = static_cast<std::function<void()> *>(args);
            (*taskPtr)();
            return nullptr;
        }

        static void default_func(){}

    public:
        enum Status
        {
            NEW,
            RUNNING,
            DETACHED,
            JOINED,
            STOPPED
        };

        template <typename Fun, typename... Args>
        Thread(std::string name = "Thread", Fun &&func = default_func, Args &&...args)
            : _name(std::move(name)), _status(NEW)
        {
            // 使用lambda和元组封装参数; 要传递参数的拷贝，需要使用make_tuple
            auto task = [func = std::forward<Fun>(func),
                         args = std::forward_as_tuple(std::forward<Args>(args)...)]() mutable
            {
                std::apply(func, std::move(args));
            };

            // 存储任务到堆上
            _task = new std::function<void()>(std::move(task));
        }

        // 移动构造函数
        Thread(Thread &&other) noexcept
            : _tid(other._tid), _name(std::move(other._name)), _task(other._task), _status(other._status)
        {
            other._task = nullptr;
            other._status = STOPPED;
        }
        // 移动赋值
        Thread &operator=(Thread &&other) noexcept
        {
            if (this != &other)
            {
                // 释放当前资源
                if (_task)
                    delete static_cast<std::function<void()> *>(_task);
                // 转移资源
                _tid = other._tid;
                _name = std::move(other._name);
                _task = other._task;
                _status = other._status;
                // 置空原对象
                other._task = nullptr;
                other._status = STOPPED;
            }
            return *this;
        }

        // 禁用拷贝构造和赋值
        Thread(const Thread &) = delete;
        Thread &operator=(const Thread &) = delete;

        ~Thread()
        {
            // 确保资源正确释放
            if (_status == RUNNING)
            {
                std::cerr << "线程[" + _name + "]的对象在未被等待或分离的情况下被释放" << std::endl;
                Stop();
            }

            delete static_cast<std::function<void()> *>(_task);
        }

        bool Start()
        {
            if (_status != NEW)
                return false;

            int n = pthread_create(&_tid, nullptr, start_routine, _task);
            if (n != 0)
            {
                std::cerr << "线程[" + _name + "]启动失败: " << strerror(n) << std::endl;
                return false;
            }
            _status = RUNNING;
            SetName(_name);
            return true;
        }

        bool Detach()
        {
            if (_status == RUNNING)
            {
                int n = pthread_detach(_tid);
                if (n != 0)
                {
                    std::cerr << "线程[" + _name + "]分离失败: " << strerror(n) << std::endl;
                    return false;
                }
                _status = DETACHED;
                std::cout << "线程[" + _name + "]分离成功" << std::endl;
                return true;
            }

            std::cerr << "线程[" + _name + "]不可被分离!" << std::endl;
            return false;
        }

        bool Join()
        {
            if (_status == RUNNING)
            {
                int n = pthread_join(_tid, nullptr);
                if (n != 0)
                {
                    std::cerr << "线程[" + _name + "]等待失败: " << strerror(n) << std::endl;
                    return false;
                }
                _status = JOINED;
                std::cout << "线程[" + _name + "]等待成功" << std::endl;
                return true;
            }

            std::cerr << "线程[" + _name + "]不可被等待!" << std::endl;
            return false;
        }

        bool Stop()
        {
            if (_status == RUNNING || _status == DETACHED)
            {
                int n = pthread_cancel(_tid);
                if (n != 0)
                {
                    std::cerr << "线程[" + _name + "]终止失败: " << strerror(n) << std::endl;
                    return false;
                }
                _status = STOPPED;
                std::cout << "线程[" + _name + "]终止成功" << std::endl;
                return true;
            }

            std::cerr << "线程[" + _name + "]不可被终止!" << std::endl;
            return false;
        }

        pthread_t GetId() const { return _tid; }
        static pthread_t GetMyId() { return pthread_self(); }

        const std::string &GetName() const { return _name; }
        static std::string GetMyName() 
        {
            char name[128];
            pthread_getname_np(GetMyId(), name, sizeof(name));
            return std::string(name);
        }
        void SetName(const std::string name)
        {
            _name = move(name);
            if(_status == RUNNING || _status == DETACHED)
                pthread_setname_np(_tid, _name.c_str());
        }

        Status GetStatus() const { return _status; }

    private:
        pthread_t _tid;
        std::string _name;
        void *_task;
        Status _status;
    };
}